﻿#region License

/**
     * Copyright (C) 2010 Rafael Vasco (rafaelvasco87@gmail.com)
     * 
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * as published by the Free Software Foundation; either version 2
     * of the License, or (at your option) any later version.

     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU General Public License for more details.

     * You should have received a copy of the GNU General Public License
     * along with this program; if not, write to the Free Software
     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
     */

#endregion

using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using SpriteVortex.Helpers;
using SpriteVortex.Helpers.Packing;


namespace SpriteVortex
{
    public enum ExportResult
    {
        ExportedAll,
        ExportedOnlySpriteMap,
        Nothing
    }

    public static class Exporter
    {
        public static ExportResult ExportSpriteMapping(SpriteSheet spriteSheet, List<Animation> animations, string path)
        {
            if (spriteSheet.Frames.Count == 0)
            {
                return ExportResult.Nothing;
            }

            bool spriteSheetFinalIsCopy = false;

            SpriteSheet spriteSheetFinal;

            if (Configuration.PackSpriteSheetWhenExportingSpriteMap)
            {
                SpriteSheetPacker packer = new SpriteSheetPacker();


                if (packer.PackSpriteSheet(spriteSheet, Configuration.ForcePowTwo, Configuration.ForceSquare,
                                           Configuration.Padding, true, Application.Instance.MaxTexSize.Width,
                                           Application.Instance.MaxTexSize.Height, out spriteSheetFinal))
                {
                    string spriteSheetFileName = Path.GetFileName(spriteSheetFinal.FullPath);
                    string pathToExport = Path.GetDirectoryName(spriteSheetFinal.FullPath);

                    if (pathToExport != null && spriteSheetFileName != null)
                    {
                        spriteSheetFileName = spriteSheetFileName.Insert((spriteSheetFileName.Length - 1) - 3, "_packed");

                        pathToExport = Path.Combine(pathToExport, spriteSheetFileName);
                        spriteSheetFinal.FullPath = pathToExport;


                        spriteSheetFinalIsCopy = true;
                    }
                    else
                    {
                        return ExportResult.Nothing;
                    }
                }
                else
                {
                    return ExportResult.Nothing;
                }
            }
            else
            {
                spriteSheetFinal = spriteSheet;
            }

            bool noFrames = false;


            XMLWriter xmlWriter = new XMLWriter(path);

            xmlWriter.CreateDocWithRoot("SpriteMapping", "::Sprite Mapping generated by Sprite Vortex::");

            xmlWriter.OpenNewElement("Texture");
            xmlWriter.AddAttribute("Path", PathHelper.MakeRelativePath(spriteSheetFinal.FullPath, path));
            xmlWriter.AddAttribute("Name", PathHelper.GetFileName(spriteSheetFinal.FullPath));
            xmlWriter.CloseCurrentElement();


            xmlWriter.OpenNewElement("TransparentColors");


            if (!Configuration.OverwriteImageWhenTransparencyModified)
            {
                if (spriteSheet.TransparentColors.Count > 0)
                {
                    foreach (var color in spriteSheetFinal.TransparentColors)
                    {
                        xmlWriter.AddCompleteElementWithAttribute("Color", "Value", color.Argb.ToString());
                    }
                }
            }


            xmlWriter.CloseCurrentElement();

            xmlWriter.OpenNewElement("Sprites");
            foreach (SpriteSheetFrame spriteSheetFrame in spriteSheetFinal.Frames)
            {
                xmlWriter.OpenNewElement("Sprite");
                xmlWriter.AddAttribute("Name", spriteSheetFrame.TagName);
                xmlWriter.AddAttribute("Id", spriteSheetFrame.Id.ToString());

                xmlWriter.OpenNewElement("Coordinates");

                xmlWriter.AddCompleteElmentWithInnerText("X", spriteSheetFrame.X.ToString());
                xmlWriter.AddCompleteElmentWithInnerText("Y", spriteSheetFrame.Y.ToString());
                xmlWriter.AddCompleteElmentWithInnerText("Width", spriteSheetFrame.Width.ToString());
                xmlWriter.AddCompleteElmentWithInnerText("Height", spriteSheetFrame.Height.ToString());

                xmlWriter.CloseCurrentElement();

                xmlWriter.CloseCurrentElement();
            }
            xmlWriter.CloseCurrentElement();

            if (animations != null)
            {
                bool hasFrames = false;
                foreach (var animation in animations)
                {
                    if (animation.Frames.Count > 0)
                    {
                        hasFrames = true;
                        break;
                    }
                }

                if (hasFrames)
                {
                    xmlWriter.OpenNewElement("Animations");

                    foreach (var animation in animations)
                    {
                        xmlWriter.OpenNewElement("Animation");
                        xmlWriter.AddAttribute("Name", animation.Name);
                        xmlWriter.AddAttribute("FrameRate", animation.FrameRate.ToString());
                        xmlWriter.AddAttribute("Loop", animation.Loop.ToString());
                        xmlWriter.AddAttribute("PingPong", animation.PingPong.ToString());

                        xmlWriter.OpenNewElement("Frames");

                        foreach (var frame in animation.Frames)
                        {
                            xmlWriter.OpenNewElement("Frame");
                            xmlWriter.AddAttribute("SpriteId", frame.SpriteFrame.SpriteFrameId.ToString());
                            xmlWriter.AddAttribute("OriginX", frame.OriginX.ToString());
                            xmlWriter.AddAttribute("OriginY", frame.OriginY.ToString());
                            xmlWriter.AddAttribute("OffSetX", frame.OffSetX.ToString());
                            xmlWriter.AddAttribute("OffSetY", frame.OffSetY.ToString());
                            xmlWriter.AddAttribute("Duration", GlobalizationHelper.FormatNumber(frame.FrameDuration));

                            xmlWriter.CloseCurrentElement();
                        }

                        xmlWriter.CloseCurrentElement();

                        xmlWriter.CloseCurrentElement();
                    }
                }
                else
                {
                    noFrames = true;
                }
            }


            if (Configuration.PackSpriteSheetWhenExportingSpriteMap ||
                (Configuration.OverwriteImageWhenTransparencyModified && spriteSheetFinal.TransparentColors.Count > 0))
            {
                ExportSpriteSheetImage(spriteSheetFinal, spriteSheetFinal.FullPath);
            }

            xmlWriter.Save();


            if (spriteSheetFinalIsCopy)
            {
                spriteSheetFinal.Texture.Dispose();
            }


            return noFrames ? ExportResult.ExportedOnlySpriteMap : ExportResult.ExportedAll;
        }

        public static void ExportSpriteSheetImage(SpriteSheet spriteSheet, string savePath)
        {
            var tempBitmap = spriteSheet.Texture.Surface.ToBitmap();
            tempBitmap.Save(savePath, ImageFormat.Png);
            tempBitmap.Dispose();
        }

        public static void ExportSpriteSheetImage(SpriteSheet spriteSheet, Rectangle region, string savePath)
        {
            var tempBitmap = spriteSheet.Texture.Surface.ToBitmap(region);
            tempBitmap.Save(savePath, ImageFormat.Png);
            tempBitmap.Dispose();
        }
    }
}